#include "../utest.h"
#include "../ioc.h"
#include <Os.h>


TEST(IocReadWriteInSingleCore)
{
	VAR(Std_ReturnType, AUTOMATIC) ret = IOC_E_OK;
	VAR(int, AUTOMATIC) a = 0;
	VAR(int, AUTOMATIC) b = 0;
	VAR(int, AUTOMATIC) c = 0;
	VAR(int, AUTOMATIC) i = 0;
	/**
	 * 单核心上的无队列单次读写测试
	 * 要求写入和读出数据一致
	*/
	{
		a = 0;
		b = 1;
		c = 2;
		ret = IocWrite_FirstDemo(&a, sizeof(a), &b, sizeof(b), &c, sizeof(c));
		ASSERT_EQ(ret, IOC_E_OK);
		
		a = 0; 
		b = 0;
		c = 0;
		ret = IocRead_FirstDemo(&a, sizeof(a), &b, sizeof(b), &c, sizeof(c));
		ASSERT_EQ(ret, IOC_E_OK);
		ASSERT_EQ(a, 0);
		ASSERT_EQ(b, 1);
		ASSERT_EQ(c, 2);
	}

	/**
	 * 单核心上的无队列多次读写测试
	 * 要求写入的最后一次数据和读出的数据一致，满足 last is best要求
	*/
	{
		a = 0;
		b = 1;
		c = 2;
		for (i = 0; i < 3; i++) {
			a++;
			b++;
			c++;
			ret = IocWrite_FirstDemo(&a, sizeof(a), &b, sizeof(b), &c, sizeof(c));
			ASSERT_EQ(ret, IOC_E_OK);
		}
		a = 0; 
		b = 0;
		c = 0;
		ret = IocRead_FirstDemo(&a, sizeof(a), &b, sizeof(b), &c, sizeof(c));
		ASSERT_EQ(ret, IOC_E_OK);
		ASSERT_EQ(a, 3);
		ASSERT_EQ(b, 4);
		ASSERT_EQ(c, 5);
	}
}

TEST(IocSendRecInSingleCore)
{
	VAR(Std_ReturnType, AUTOMATIC) ret = IOC_E_OK;
	VAR(int, AUTOMATIC) a = 0;
	VAR(int, AUTOMATIC) b = 0;

	/**
	 * 单核心上的无组单次读写测试
	 * 要求读出和写入的数据一致
	*/
	{
		a = 666;
		ret = IocSend_SecondDemo(&a,sizeof(a));
		ASSERT_EQ(IOC_E_OK, ret);
		a = 0;
		ret = IocReceive_SecondDemo(&a,sizeof(a));
		ASSERT_EQ(IOC_E_OK, ret);
		ASSERT_EQ(a, 666);
	}

	/**
	 * 单核心上的单次组读写测试
	 * 要求读出和写入的数据一致
	*/
	{
		
		a = 999;
		b = 333;
		ret = IocSend_FirstDemo(&a, sizeof(a), &b, sizeof(b));
		ASSERT_EQ(IOC_E_OK, ret);
		a = 0;
		b = 0;
		ret = IocReceive_FirstDemo(&a, sizeof(a), &b, sizeof(b));
		ASSERT_EQ(IOC_E_OK, ret);
		ASSERT_EQ(a, 999);
		ASSERT_EQ(b, 333);
	}

	/**
	 * 单核心上的组队列测试
	 * 要求: 写满缓冲区，然后从缓冲区读出的数据与写入的数据在顺序和数据上一致
	*/
	{
		VAR(int, AUTOMATIC) count = 0, count2 = 0;
		VAR(int, AUTOMATIC) abak = 0, bbak = 0;
		a = 0;
		b = 0; 
	
		while(1) {
			ret = IocSend_FirstDemo(&a, sizeof(a), &b, sizeof(b));
			if (ret != IOC_E_OK) {
				ASSERT_EQ(ret, IOC_E_LIMIT);
				break;
			}
			a++;
			b++;
			count++;
		}
		ASSERT_EQ(ret, IOC_E_LIMIT);
		ASSERT_NE(count, 0);
		
		while(1) {
			ret = IocReceive_FirstDemo(&a, sizeof(a), &b, sizeof(b));
			if (count2 == 0) {
				ASSERT_EQ(IOC_E_LOST_DATA, ret);
			}
			if (ret == IOC_E_NO_DATA) {
				ASSERT_EQ(count2, count);
				break;
			}
			if (count2 > count) {
				ASSERT_TRUE(0);
			}
			ASSERT_EQ(a, abak);
			ASSERT_EQ(b, bbak);
			abak++;
			bbak++;
			count2++;
		}
		ret = IocReceive_FirstDemo(&a, sizeof(a), &b, sizeof(b));
		ASSERT_EQ(ret, IOC_E_NO_DATA);
	}
}

TEST(IocSendRecInMultCore)
{
	VAR(unsigned int, AUTOMATIC) count = 500;
	VAR(unsigned int, AUTOMATIC) printk_count = 0;
	VAR(Std_ReturnType, AUTOMATIC) ret = IOC_E_OK;
	VAR(int, AUTOMATIC) a = 0;
	VAR(int, AUTOMATIC) b = 1;
	VAR(int, AUTOMATIC) c = 3;

	/**
	 * 在核心上调用不属于此核心的IOC函数
	 * 要求返回错误，不能执行发送功能
	*/
	ret = IocRead_CORE0_TO_CORE1(&a, sizeof(a), &b, sizeof(b), &c, sizeof(c));
	ASSERT_EQ(ret, IOC_E_NOK);
	ret = IocRec_QUEUE_CORE0_TO_CORE1(&a, sizeof(a), &b, sizeof(b), &c, sizeof(c));
	ASSERT_EQ(ret, IOC_E_NOK);

	LOGI("通知核心1上的测试开始");
	a = IOCTESTSTART;
	ret = IocWrite_CORE0_TO_CORE1(&a, sizeof(a), &b, sizeof(b), &c, sizeof(c));
	ASSERT_EQ(ret, IOC_E_OK);

	LOGI("等待核心1上的测试应答");
	do {
		ret = IocRead_CORE1_TO_CORE0(&a, sizeof(a), &b, sizeof(b), &c, sizeof(c));
		if (printk_count == 0 && ret != IOC_E_OK) {
			LOGI("核心1上的测试应答未响应");
		}
		if (ret == IOC_E_OK && a != IOCTESTSTART) {
			LOGI("应答数值错误 %d", a);
		}
		printk_count++;
		printk_count = printk_count % 10000;
	} while (ret != IOC_E_OK || a != IOCTESTSTART);

	/**
	 * 测试非队列的组写入
	 * 要求连续多次发送一组数据时，如果接受方读取了数据，要求读出的数据是当时最后一次写入的，并且无错
	*/
	count = 5;
	while (count --) {
		a++;
		b = a+1;
		c = a+3;
		if (a >= count) {
			a = 0;
			b = 1;
			c = 3;
		}
		ret = IocWrite_CORE0_TO_CORE1(&a, sizeof(a), &b, sizeof(b), &c, sizeof(c));
		if (IOC_E_OK != ret) {
			LOGI("IocWrite_CORE0_TO_CORE1 error == %d\n", ret);
			ASSERT_EQ(ret, IOC_E_OK);
		}
	}
	/* 发送信号，结束write_read 测试 */
	a = IOCTESTEND;
	ret = IocWrite_CORE0_TO_CORE1(&a, sizeof(a), &b, sizeof(b), &c, sizeof(c));
	ASSERT_EQ(ret, IOC_E_OK);
	
	LOGI("开始测试IocSend_QUEUE_CORE0_TO_CORE1");
	count = 5;
	a = 0;
	b = 1;
	c = 3;
	/**
	 * 测试非队列的队列写入
	 * 要求连续多次发送一组数据时，如果接受方读取了数据，要求读出的数据是与写入时的数据在顺序和数值上保持一致
	*/
	while(count) {
		if (count == 1) {
			a = IOCTESTEND;
		}
		ret = IocSend_QUEUE_CORE0_TO_CORE1(&a, sizeof(a), &b, sizeof(b), &c, sizeof(c));
		if (ret == IOC_E_OK) {
			count--;
			a++;
			b = a+1;
			c = a+3;
			if (a == 500) {
				a = 0;
				b = 1;
				c = 3;
			}
		} else if (IOC_E_LIMIT != ret) {
			LOGI("IocSend_QUEUE_CORE0_TO_CORE1 error == %d\n", ret);
			EXPECT_TRUE(0);
		} else {
			if (printk_count == 0) {
				LOGI("IocSend_QUEUE_CORE0_TO_CORE1 ret = %d", ret);
			}
			printk_count++;
			printk_count = printk_count % 10000;
		}
	}

	printk_count = 0;
	do {
		ret = IocRead_CORE1_TO_CORE0(&a, sizeof(a), &b, sizeof(b), &c, sizeof(c));
		if (printk_count == 0) {
			if (ret != IOC_E_OK) {
				LOGI("核心1上的结束测试应答未响应");
			}
		}
		if (ret == IOC_E_OK && a != IOCTESTEND) {
			LOGI("应答数值错误 %d", a);
		}
		printk_count++;
		printk_count = printk_count % 10000;
	} while (ret != IOC_E_OK || a != IOCTESTEND);
}

TEST_SUIT(IOC)
{
	UTEST_CASE(IocReadWriteInSingleCore);
	UTEST_CASE(IocSendRecInSingleCore);
	UTEST_CASE(IocSendRecInMultCore);
}